<?php
/**
 * sqlite数据库驱动
 *
 * @package if
 * @subpackage module.db.drivers
 * @since 1.0
 */
class IDbSqliteDriver extends IDbDriver {
	protected $startQuote = "\"";
	protected $endQuote = "\"";
	
	protected $commands = array(
		"begin"    => "BEGIN TRANSACTION",
		"commit"   => "COMMIT TRANSACTION",
		"rollback" => "ROLLBACK TRANSACTION"
	);	
	
	protected $metaTableSQL = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
	
	private $db;
	
	/**
	 * 构造器
	 *
	 * @param array $config 连接配置
	 * @since 1.0
	 */
	function __construct(array $config) {
		if (!extension_loaded("sqlite")) {
			throw new IDbException("sqlite extension not be loaded", 0x100080);
		}
		
		parent::__construct($config);
		
		$charset = $this->config("charset");
		if ($charset != "") {
			$this->exec("PRAGMA encoding=\"{$charset}\"");
		}
	}
	
	function checkOptions() {
		$path = $this->config("path");
		$mode = $this->config("mode");
		if ($path == "") {
			throw new IDbException("sqlite db path must be defined", 0x100081);
		}
		if ($mode == "") {
			$mode = 0666;
		}
		$error = "";
		if ($this->config("persist")) {
			$this->db = @sqlite_popen($path, $mode, $error);
		}
		else {
			$this->db = @sqlite_open($path, $mode, $error);
		}
		if (!$this->db) {
			throw new IDbException("can't read the db '{$path}', " . $error, 0x100082);
		}
	}
	
	
	/**
	 * 取得表的描述
	 *
	 * @param string $name 表名称
	 * @return array
	 * @since 1.0
	 */
	function describeTable($name) {
		$array = $this->fetchAll($this->nativeExec("PRAGMA table_info(\"" . $name . "\")"));
		$fields = array();
		foreach ($array as $row) {
			$type = explode("(", $row["type"]);
			$size = null;
			if (count($type) == 2) {
			    $size = trim($type[1], ")");
			}
			$column = $row["name"];
			$fields[$column] = array(	
				"name" => $column,
				"type" => $type[0],
				"max_length" => $size,
				"not_null"  => (bool)$row["notnull"],
				"primary_key" => ($row["pk"] == 1),
				"has_default" => !is_null($row["dflt_value"]),
				"default_value" => $row["dflt_value"]
			);
			$fields[$column]["data_type"] = $this->dataType($fields[$column]);
		}
		return $fields;
	}
	
	/**
	 * 连接数据库
	 *
	 * @since 1.0
	 */
	function nConnect() {
		return $this->db;
	}
	
	/**
	 * 关闭连接
	 *
	 * @since 1.0
	 */
	function nClose() {
		sqlite_close($this->db);
	}
	
	/**
	 * 取得最后插入的ID
	 *
	 * @param string $name 可能需要的字段名称
	 * @return string
	 * @since 1.0
	 */
	function lastInsertId($name = null) {
		return sqlite_last_insert_rowid($this->db);
	}
	
	/**
	 * 给SQL加入limit条件
	 *
	 * @param string $sql SQL
	 * @param integer $count 总数
	 * @param integer $offset 开始位置
	 * @return string
	 * @since 1.0
	 */
	function nLimit($sql, $count, $offset = 0) {
		return $sql . " LIMIT {$offset},{$count}";
	}
	
	/**
	 * 引住数据
	 *
	 * @param mixed $data 需要加引号的数据
	 * @return mixed
	 * @since 1.0
	 */
	function nQuote($data) {
		if (is_int($data) || is_float($data)) {
			return $data;
		}
		if (is_null($data)) {
			return "NULL";
		}
		return "'" . sqlite_escape_string($data) . "'";
	}
	
	/**
	 * 执行一条语句，并返回影响的行数
	 *
	 * @param string $sql SQL
	 * @return integer
	 * @since 1.0
	 */
	function exec($sql) {
		$result = $this->nativeExec($sql);
		return sqlite_changes($this->db);
	}
	
	/**
	 * 利用原生的方法/函数执行语句，并返回执行结果
	 *
	 * @param string $sql SQL
	 * @return mixed
	 * @since 1.0
	 */
	function nativeExec($sql) {
		 return sqlite_query($sql, $this->db);
	}
	
	/**
	 * 执行一条语句，返回预处理语句
	 *
	 * @param string $sql SQL
	 * @param integer $fetchType 返回方式，参见IDb::FETCH_*
	 * @return IDbStatment
	 * @since 1.0
	 */
	function query($sql, $fetchType = IDb::FETCH_ASSOC) {
		$stmt = $this->prepare($sql);
		$args = func_get_args();
		unset($args[0]);
		call_user_func_array(array($stmt, "setFetchMode"), $args);
		$stmt->execute();
		return $stmt;
	}
	
	/**
	 * 取得一行记录
	 *
	 * @param mixed $result nativeExec返回的结果集
	 * @param integer $fetchType 返回方式，参见IDb::FETCH_*
	 * @param integer $columnIndex 列序号，对于$fetchType为IDb::FETCH_COLUMN有效
	 * @since 1.0
	 */
	function fetch($result, $fetchType = IDb::FETCH_BOTH, $columnIndex = 0) {
		switch ($fetchType) {
			case IDb::FETCH_BOTH:
				return sqlite_fetch_array($result, SQLITE_BOTH);
				break;
			case IDb::FETCH_ASSOC:
				return sqlite_fetch_array($result, SQLITE_ASSOC);
			case IDb::FETCH_NUM:
				return sqlite_fetch_array($result, SQLITE_NUM);
			case IDb::FETCH_OBJ:
				return sqlite_fetch_OBJECT($result);
			case IDb::FETCH_COLUMN:
				$row = sqlite_fetch_array($result, SQLITE_NUM);
				if (!empty($row)) {
					if (array_key_exists($columnIndex, $row)) {
						return $row[$columnIndex];
					}
				}
		}
		return null;
	}
	
	/**
	 * 取得错误
	 *
	 * 返回格式为：
	 * array (
	 *   "code" => 1002,
	 * 	 "message" => "syntax error"
	 * )
	 * 
	 * 如果返回是一个空数组，意味着没有错误发生
	 * 
	 * @since array
	 * @since 1.0
	 */
	function error() {
		$code = sqlite_last_error($this->db);
		if ($code) {
			return array(
				"code" => $code,
				"message" => sqlite_error_string($code)
			);
		}
		return array();
	}
	
	/**
	 * 取得影响的行数
	 *
	 * @param mixed $result nativeExec的结果集
	 * @since 1.0
	 */
	function rowCount($result) {
		return is_resource($result) ? sqlite_num_rows($result) : sqlite_changes($this->db);
	}
	
	function move($result, $offset) {
		return sqlite_seek($result, $offset);
	}
}

?>